package com.heima.article.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.feign.BehaviorFeign;
import com.heima.article.feign.UserFeign;
import com.heima.article.mapper.ArticleConfigMapper;
import com.heima.article.mapper.ArticleContentMapper;
import com.heima.article.mapper.ArticleMapper;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.ApCollectionService;
import com.heima.article.service.AuthorService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.dtos.ArticleInfoDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.behavior.pojos.*;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUserFan;
import com.heima.model.user.pojos.ApUserFollow;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
@Transactional
public class ApArticleServiceImpl extends ServiceImpl<ArticleMapper, ApArticle> implements ApArticleService {

    @Autowired
    ArticleConfigMapper articleConfigMapper;

    @Autowired
    ArticleContentMapper articleContentMapper;

    @Autowired
    ArticleMapper articleMapper;

    @Value("${fdfs.url}")
    private String fastUrl;

    // 单页最大加载的数字
    private final static short MAX_PAGE_SIZE = 50;

    @Autowired
    BehaviorFeign behaviorFeign;

    @Autowired
    AuthorService authorService;

    @Autowired
    ApCollectionService apCollectionService;

    @Autowired
    UserFeign userFeign;



    //完成以下功能需要的数据有：
    // 1.当前用户的行为实体
    // 2.当前的文章id
    // 3.需要前端传来的作者id 去查询到属于作者的用户id  用于查询关注表

    //需要提供三个feign
    //1.用户库里的关注表和粉丝表 返回值：各自的pojo对象 参数：登录人的用户id  文章发布者的用户id
    //2.行为库的 点赞表     返回值：点赞表的pojo      参数：登录人的行为实体id 文章的id
    //3.行为库的 不喜欢表   返回值：不喜欢表的pojo    参数：登录人的行为实体id 文章的id

    //1. ----此条作废-->>> 行为库的 关注表     返回值：List<关注表pojo>  参数：登录人的行为实体id 文章的id 此文章作者的用户id

    //本库的 收藏表        返回值：收藏表的pojo      参数：登录人的行为实体id 文章的id
    //根据行为实体查询对应的4张表

    @Override
    public ResponseResult loadArticleBehavior(ArticleInfoDto dto) {
        //判断参数
        if (dto == null || dto.getArticleId() == null || dto.getAuthorId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 登录人的id
        Integer myId = AppThreadLocalUtils.getUser().getId();
        if (myId==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        ApAuthor auth = authorService.getById(dto.getAuthorId());
        //文章发布的作者

        //根据用户id或设备id查询行为实体
        ApBehaviorEntry enrty = behaviorFeign.getEnrty(myId, dto.getEquipmentId());
        if (enrty == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "没有行为实体");
        }

        //返回值：{"isfollow":true,"islike":true,"isunlike":false,"iscollection":true}
        boolean isfollow = false;
        boolean islike = false;
        boolean isunlike = false;
        boolean iscollection = false;

        ApLikesBehavior like = behaviorFeign.getLike(enrty.getId(), dto.getArticleId());
        if (like!=null&&like.getOperation().equals((short)0)){
            //点赞表不为空 并且Operation为点赞 才会为true 其他情况是false
            islike=true;
        }

        ApUnlikesBehavior noLike = behaviorFeign.getNoLike(enrty.getId(), dto.getArticleId());
        if (noLike!=null&&noLike.getType().equals((short)0)){
            //不喜欢表不为空 并且type为不喜欢 才会为true 其他情况为false
            isunlike=true;
        }

        //List<ApFollowBehavior> followList = behaviorFeign.getFollowList(enrty.getId(), dto.getArticleId(), auth.getUserId());
        ApUserFan userFan = userFeign.getUserFan(auth.getUserId(), myId.longValue());
        ApUserFollow userFollow = userFeign.getUserFollow(myId, auth.getUserId());
        if (userFan!=null&&userFollow!=null){
            //如果关注表和粉丝表同时存在 才算关注
            //不能拿行为库的关注表做比较 因为那里的设定是 关注了就存数据 取关也不删数据
            isfollow=true;
        }

        ApCollection collect = apCollectionService.getOne(Wrappers.<ApCollection>lambdaQuery().eq(ApCollection::getEntryId, enrty.getId())
                .eq(ApCollection::getArticleId, dto.getArticleId()));
        if (collect!=null){
            iscollection=true;
        }

        HashMap<String, Object> map = new HashMap<>();
        map.put("isfollow", isfollow);
        map.put("islike", islike);
        map.put("isunlike", isunlike);
        map.put("iscollection", iscollection);

        return ResponseResult.okResult(map);
    }


    /**
     * app端查询文章详情
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadArtilceInfo(ArticleInfoDto dto) {
        if (dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        ApArticleConfig config = articleConfigMapper.selectOne(Wrappers.<ApArticleConfig>lambdaQuery()
                .eq(ApArticleConfig::getArticleId, dto.getArticleId()));
        if (config == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        if (config.getIsDown() || config.getIsDelete()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章已下架或删除！");
        }

        ApArticleContent content = articleContentMapper.selectOne(Wrappers.<ApArticleContent>lambdaQuery()
                .eq(ApArticleContent::getArticleId, dto.getArticleId()));
        if (content == null) return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        HashMap<String, Object> map = new HashMap<>();
        map.put("content", content);
        map.put("config", config);
        return ResponseResult.okResult(map);
    }

    /**
     * app端查询文章列表
     *
     * @param loadtype 1为加载更多  2为加载最新
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(Short loadtype, ArticleHomeDto dto) {
        if (dto.getSize() == null) {
            dto.setSize(10);
        }

        int min = Math.min(dto.getSize(), 50);
        dto.setSize(min);

        if (dto.getTag() == null) {
            dto.setTag("__all__");
        }

        if (!loadtype.equals((short) 1) && !loadtype.equals((short) 2)) loadtype = (short) 1;

        if (dto.getMaxBehotTime() == null) dto.setMaxBehotTime(new Date());
        if (dto.getMinBehotTime() == null) dto.setMinBehotTime(new Date());

        List<ApArticle> apArticle = articleMapper.loadArticleList(dto, loadtype);
        ResponseResult responseResult = ResponseResult.okResult(apArticle);
        responseResult.setHost(fastUrl);
        return responseResult;

//        TODO:方法解释：
//        在刚进入列表页面时 前端传来的是 最小时间1970年 最大时间为2603年 而走的controller是 load方法
//        传到service的type就是1（查询更多） 那mapper层查询的时候就是按照 小于2603年的发布时间的文章 然后查询10条 倒序排列
//        这样查询出来的数据 就是正常的10条数据 最新的10条 因为有倒序 前端传来的条数 一直都是10条 这里面判断size的代码是多余的
//        当前端下拉 查询最新数据时 会发来最大时间（上次查询出来的10条数据里最大的时间） 和最小时间（上次查询到的10条数据中最小的时间）
//        type为2 mapper查询大于最大时间的数据10条倒序返回 不用担心这样之前第一次查询的10条会没有了 因为前端做了保存 在我们执行
//        查询最新的方法时 查询到的数据会累加在之前的数据之上 这样就会显示第一次查询和第二次查询的所有数据 时间最大的在上面
//        而在执行查询更多的方法时 前端传来的也是当前数据中 最大的时间的最小的时间 type为1 mapper会去查询小于最小时间的数据10条
//        返回后 前端会拼接到之前所有数据的底部 这样一来就实现了加载最新和加载更多的需求
    }


    @Override
    public ResponseResult saveArtilce(ArticleDto articleDto) {
        if (articleDto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        ApArticle apArticle = new ApArticle();
        BeanUtils.copyProperties(articleDto, apArticle);

        if (articleDto.getId() == null) {

            save(apArticle);

            ApArticleContent apArticleContent = new ApArticleContent();
            apArticleContent.setContent(articleDto.getContent());
            apArticleContent.setArticleId(apArticle.getId());
            articleContentMapper.insert(apArticleContent);

            ApArticleConfig config = new ApArticleConfig();
            config.setArticleId(apArticle.getId());
            config.setIsComment(true);
            config.setIsDelete(false);
            config.setIsForward(true);
            config.setIsDown(false);
            articleConfigMapper.insert(config);

        } else {

            ApArticle byId = getById(articleDto.getId());
            if (byId == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "app文章不存在");
            }

            updateById(apArticle);

            ApArticleContent one = articleContentMapper.selectOne(Wrappers.<ApArticleContent>lambdaQuery()
                    .eq(ApArticleContent::getArticleId, articleDto.getId()));
            one.setContent(articleDto.getContent());
            articleContentMapper.updateById(one);
        }

        return ResponseResult.okResult(apArticle.getId());
    }


}
